//MIPS alu module




module ALU (operand_a, operand_b, op, outcome, z);
  //operation supported
  parameter ADD=6'b100000;
  parameter AND=6'b100100;
  parameter OR=6'b100101;
  parameter SUB=6'b100010;
  parameter SLT=6'b101010;
  //mostly for nop, for a general implementation of instructions
  parameter SLL=6'b000000;
  //operation supported




  parameter word_size=32;
  parameter op_size=6;

  //begin declaration
  input [word_size-1:0] operand_a;
  input [word_size-1:0] operand_b;
  input [op_size-1:0] op;
  output [word_size-1:0] outcome;
  output z; //flag of the latest computation

  //register declaration
  reg z,outcome;

  always @ (operand_a or operand_b or op ) begin

    //do the actual computation
    case (op) ADD:  begin
                        outcome=operand_a+operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
              SUB:  begin
                        outcome=operand_a-operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
              AND:  begin
                        outcome=operand_a&operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
              OR:   begin
                        outcome=operand_a|operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
              SLT:  begin
                        outcome=operand_a<operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
              SLL:  begin
                        outcome=operand_a << operand_b;
                        //set flags
                        z=(outcome==0)? 1:0;
                    end
      default: $display("%g\top %b: not defined",$time,op);
    endcase
  end

endmodule //


// module alu_sim ();
//   parameter word_size=32;
//   parameter op_size=6;
//   //operation supported
//   parameter ADD=6'b100000;
//   parameter AND=6'b100100;
//   parameter OR=6'b100101;
//   parameter SUB=6'b100010;
//   parameter SLT=6'b101010;
//
//   parameter SLL=6'b000000;
//   //operation supported
//
//   reg [word_size-1:0] operand_a, operand_b;
//   reg [op_size-1:0] op;
//
//   wire [word_size-1:0] outcome;
//   wire z;
//
//
//   initial begin
//     $dumpfile("alu_sim.vcd");
//     $dumpvars(0,alu_sim);
//
//     $display("Time\tOp\tA\tB\tOut\tZ");
//     //register monitor
//     $monitor("%g\t%x\t%x\t%x\t%x\t%x",$time, op, operand_a, operand_b, outcome, z);
//
//     //init state
//     operand_a=0;
//     operand_b=0;
//     op=0;
//
//     #1 op=ADD;
//     #1 operand_a=31;
//     #1 operand_b=2;
//     #1 operand_a=0;
//     #1 operand_b=0;
//
//
//     #1 op=SUB;
//     #1 operand_a=2;
//     #1 operand_b=2;
//     #1 operand_a=1;
//     #1 operand_b=0;
//     #1 operand_a=0;
//
//
//     #1 op=AND;
//     #1 operand_a=31;
//     #1 operand_b=1;
//     #1 operand_a=0;
//     #1 operand_b=0;
//
//
//     #1 op=OR;
//     #1 operand_a=31;
//     #1 operand_b=0;
//     #1 operand_a=0;
//     #1 operand_b=31;
//     #1 operand_b=0;
//
//     #1 op=SLT;
//     #1 operand_a=31;
//     #1 operand_b=0;
//     #1 operand_b=33;
//     #1 operand_a=0;
//     #1 operand_b=0;
//
//     #1 op=SLL;
//     #1 operand_a=32;
//     #1 operand_b=1;
//     #1 operand_b=2;
//     #1 operand_a=0;
//     #1 operand_b=0;
//
//     //test bad operations
//     #1 op=6'b000001;
//     #1 $finish;
//
//
//
//
//   end
//
// 
//
//
//   ALU alu_mod(operand_a,operand_b,op,outcome,z);
//
// endmodule // alu_sim
